#pragma once
#include <iostream>
#include "utility/index.hpp"
#include "request_access/index.hpp"
#include "data_access/index.hpp"
#include "components/index.hpp"

using namespace std;
using namespace utility;

namespace components2 {
    class ProduceOrder : public components::EntityRequest {
    public:
        COMPONENT_INSTANCE_FUNCTION(ProduceOrder);

        ProduceOrder();

        any UpdateStatus();

        any Update2();

        any CancelReview();

        any AddUse();

    private:
        EntityData getMaterialUseOrder(const any& saleOrderId);
        entity_access::EntityType *saleOrderEntity;
        entity_access::EntityType *materialUseOrderEntity;
    };

    ProduceOrder::ProduceOrder() {
        SET_METHOD_ACTION(UpdateStatus);
        SET_METHOD_ACTION(Update2);
        SET_METHOD_ACTION(CancelReview);
        SET_METHOD_ACTION(AddUse);
        saleOrderEntity = entity_access::GetEntityType("SaleOrder");
        materialUseOrderEntity = entity_access::GetEntityType("MaterialUseOrder");
    }

    std::any ProduceOrder::UpdateStatus() {
        EntityData dict = Request->RequestEntity.GetEntityData(Entity->Name);

        auto oldEntityData = SelectEntityByPrimaryKey(QueryRequest->PrimaryKeyValue);
        if (oldEntityData.Empty()) return Request->GetMessageMap("生产订单不存在");

        auto msg = CompareVersion(dict, oldEntityData);
        if (!msg.empty()) return Request->GetMessageMap(msg);

        int status = dict.GetInt("Status");
        auto saleOrderId = oldEntityData.Get("SaleOrderId");

        bool blSucceed = true;
        try {
            DataBase->BeginTransaction();

            blSucceed = Actions::UpdateStatusAndReview(shared_from_this(), materialUseOrderEntity, dict, 4);

            if (blSucceed && status != 1) Actions::UpdateSaleStatus(shared_from_this(), oldEntityData.Get("SaleOrderId"));

            if (blSucceed) DataBase->CommitTransaction();
            else DataBase->RollbackTransaction();
        } catch (const std::exception &e) {
            DataBase->RollbackTransaction();
             throw MessageException(e.what(),"");
        }

        return GetSucceedMap(blSucceed);
    }

    any ProduceOrder::Update2() {
        EntityData dict = Request->RequestEntity.GetEntityData(Entity->Name);
        auto oldEntityData = SelectEntityByPrimaryKey(saleOrderEntity, QueryRequest->PrimaryKeyValue);
        if (oldEntityData.Empty()) return Request->GetMessageMap("销售订单不存在");

        EntityData saleOrder;
        saleOrder["RowVersion"] = dict["SaleRowVersion"];
        auto msg = CompareVersion(saleOrder, oldEntityData);
        if (!msg.empty()) return Request->GetMessageMap("数据不是最新版本，请刷新再试！");

        auto produceOrderId = dict.GetString("ProduceOrderId");

        if (produceOrderId.empty()) {
            EntityData obj = Insert();
            if (obj.ContainsKey("Succeed")) Actions::UpdateOrderCode(shared_from_this(), 4, obj.Get("ProduceOrderId"));
            return obj;
        } else {
            QueryRequest->PrimaryKeyValue = produceOrderId;
            return Update();
        }
    }

    any ProduceOrder::CancelReview() {
        Actions::SetCancelReviewEntityData(shared_from_this());
        return UpdateStatus();
    }

    any ProduceOrder::AddUse() {
        auto dict = Request->RequestEntity.GetEntityData(Entity->Name);
        auto oldEntityData = SelectEntityByPrimaryKey(QueryRequest->PrimaryKeyValue);
        if(oldEntityData.Empty()) return Request->GetMessageMap("生产订单不存在");

        auto msg = CompareVersion(dict, oldEntityData);
        if(!msg.empty()) return Request->GetMessageMap(msg);

        EntityData useOrder = getMaterialUseOrder(oldEntityData.Get("SaleOrderId"));
        bool blSucceed = true;

        try {
            DataBase->BeginTransaction();

            blSucceed = InsertEntity(materialUseOrderEntity, useOrder);
            if (blSucceed) blSucceed = components::EntityByComplexTypeOperation::EditDeleteComplexType(shared_from_this(), materialUseOrderEntity, useOrder, false);

            if(blSucceed) {
                EntityData updateEntityData;
                updateEntityData["UpdateDate"] = DateTime();
                updateEntityData["UpdateUser"] = Request->OperationUser;

                blSucceed = UpdateEntityByPrimaryKey(QueryRequest->PrimaryKeyValue, updateEntityData);
            }
            if (blSucceed) {
                DataBase->CommitTransaction();
                Actions::UpdateOrderCode(shared_from_this(), 5, useOrder.Get("UseOrderId"));
            } else DataBase->RollbackTransaction();
        } catch (const std::exception &e) {
            DataBase->RollbackTransaction();
            throw MessageException(e.what(),"");
        }

        return GetSucceedMap(blSucceed);
    }

    EntityData ProduceOrder::getMaterialUseOrder(const any& saleOrderId) {
        auto dict = Request->RequestEntity.GetEntityData(Entity->Name);
        EntityData data;

        data["SaleOrderId"] = saleOrderId;
        data["ProduceOrderId"] = QueryRequest->PrimaryKeyValue;
        data["UseEmployeeId"] = dict["UseEmployeeId"];
        data["UseDate"] = dict["UseDate"];
        data["Remark"] =  dict["UseRemark"];
        data["CreateUser"] = Request->OperationUser;

        auto details = dict.GetEntityDataList("Details");

        vector<EntityData> detailList;
        for (auto &d: details) {
            auto num = d.GetFloat("UseNum");
            if (num != 0) {
                EntityData detail;
                detail["Num"] = d["UseNum"];
                detail["DisplayIndex"] = d["DisplayIndex"];
                detail["MaterialProductId"] = d["MaterialProductId"];
                detailList.emplace_back(detail);
            }
        }

        if (detailList.empty()) throw MessageException("领用原料商品明领取数量不能都为0", "");

        data["Details"] = detailList;

        return data;
    }
}